/*
 * UT_runner.h
 *
 *  Created on: 2010-04-01
 *      Author: Godwinguo
 */

#ifndef __UT_RUNNER__
#define __UT_RUNNER__

#include "ut_features.h"

/*************************************************************************
* ENUM
*************************************************************************/

#define UT_RESULT_PASS		(0)
#define UT_RESULT_FAIL		(1)
#define UT_RESULT_SKIP		(2)

/*************************************************************************
* PROTOTYPE
*************************************************************************/

struct __struct_ut_result;
typedef struct __struct_ut_result	ut_result_t;
typedef struct __struct_ut_result *	ut_result_ptr_t;

struct __struct_ut_case;
typedef struct __struct_ut_case		ut_case_t;
typedef struct __struct_ut_case *	ut_case_ptr_t;

struct __struct_ut_group;
typedef struct __struct_ut_group	ut_group_t;
typedef struct __struct_ut_group *	ut_group_ptr_t;

/*************************************************************************
* STRUCTURE
*************************************************************************/

struct __struct_ut_result
{
	unsigned long	pass;
	unsigned long	fail;
	unsigned long	skip;
};

struct __struct_ut_case
{
	char *			name;
	char *			file;
	unsigned long	line;
	unsigned long	( * do_test )( void );
};

struct __struct_ut_group
{
	char *			name;
	ut_case_ptr_t	cases;
};

/*************************************************************************
* Macros
*************************************************************************/

#undef	UT_CASE
#define UT_CASE( __name ) \
		static unsigned long __ut_case_##__name( void )


#undef	UT_GROUP_IMPORT
#define UT_GROUP_IMPORT( __name ) \
		extern const ut_case_t __ut_group_##__name[];

#undef	UT_GROUP
#define UT_GROUP( __name ) \
		const ut_case_t __ut_group_##__name[] =

#undef	UT_ADD_CASE
#define UT_ADD_CASE( __name ) \
			{ \
				(char *)#__name, \
				(char *)__FILE__, \
				(unsigned long)__LINE__, \
				(__ut_case_##__name) \
			}

#undef	UT_LAST_CASE
#define UT_LAST_CASE \
			{ \
				0, \
				0, \
				0, \
				0 \
			}


#undef	UT_SUITE_IMPORT
#define UT_SUITE_IMPORT( __name ) \
		extern const ut_group_t __ut_suite_##__name[];

#undef	UT_SUITE
#define UT_SUITE( __name ) \
		const ut_group_t __ut_suite_##__name[] =

#undef	UT_ADD_GROUP
#define UT_ADD_GROUP( __name ) \
			{ \
				(char *)#__name, \
				(ut_case_ptr_t)(&__ut_group_##__name[0]) \
			}

#undef	UT_LAST_GROUP
#define UT_LAST_GROUP \
			{ \
				0, \
				0 \
			}

#undef	UT_EXPECT
#define UT_EXPECT( __e, __stmt ) \
		if ( !(__e) ) \
		{ \
			ut_coloring( UT_FG_RED ); \
			ut_trace( "Error : %s @ %s(%d)", #__e, __FILE__, __LINE__ ); \
			__stmt \
			ut_coloring( UT_FG_DEFAULT ); \
		}

#undef	UT_EXPECT_OR_SHOWMSG
#define UT_EXPECT_OR_SHOWMSG( __e, __msg )	UT_EXPECT( __e, { APIS_TRACE(__msg); } )

#undef	UT_EXPECT_OR_RETURN
#define UT_EXPECT_OR_RETURN( __e, __ret )	UT_EXPECT( __e, { return __ret; } )

#undef	UT_EXPECT_OR_GOTO
#define UT_EXPECT_OR_GOTO( __e, __label )	UT_EXPECT( __e, { goto __label; } )


#define UT_FG_DEFAULT	(0)
#define UT_FG_BLUE		(1)
#define UT_FG_GREEN		(2)
#define UT_FG_RED		(3)

/*************************************************************************
* DECLARATION
*************************************************************************/

#if defined(__cplusplus)
extern "C" {
#endif	// #if defined(__cplusplus)

void ut_coloring( unsigned long color );
void ut_trace( char * fmt, ... );

void ut_test_groups( ut_group_ptr_t pgroups, unsigned long ngroups );

#if defined(__cplusplus)
}
#endif	// #if defined(__cplusplus)

/*************************************************************************
* MACRO
*************************************************************************/

#undef	UT_RUN_SUITE
#define UT_RUN_SUITE( __name ) \
		ut_test_groups( (ut_group_ptr_t)&__ut_suite_##__name[0], \
						(unsigned long)(sizeof(__ut_suite_##__name) / sizeof(__ut_suite_##__name[0]) - 1) \
		)

#endif  // #ifndef __UT_RUNNER__